#pragma once

#include <algorithm>
#include <iostream>
#include <vector>

class Cards;

class Card {
  friend class Cards;
  friend std::ostream &operator<<(std::ostream &, const Cards &);
  friend std::ostream& operator<<(std::ostream& out, const Card& x){
      return (out<<x.point);
  }

private:
  int color; // 花色
  int point; // 点数

public:
  Card() {}
  Card(int co, int po) : color(co), point(po) {}

  Card(const Card &x) {
    color = x.color;
    point = x.point;
  }

  int getPoint()const{return point;}

  // 符合斗地主规则，避免一堆傻了吧唧的判断
  bool operator<(const Card &x) const {
    if (x.point == 15)
      return true;
    if (x.point == 14)
      return !(point == 15);

    if (point >= 14)
      return false;

    if (point >= 3 && x.point >= 3)
      return (point < x.point);

    if (point >= 3)
      return true;
    if (x.point >= 3)
      return false;

    return (point < x.point);
  }

  bool operator==(const Card &x) const { return (point == x.point); }
  bool operator!=(const Card &x) const { return (point != x.point); }
  bool operator<=(const Card &x) const { return !(x < *this); }
  bool operator>=(const Card &x) const { return !(*this < x); }
  bool operator>(const Card &x) const { return (x < *this); }

  Card &operator++(int) {
    if (point == 13) {
      point = 1;
    } else if (point == 2) {
      point = 14;
    } else
      point++;
    return *this;
  }

  Card operator+(int x) {
    Card out = *this;
    while (x--)
      out++;
    return out;
  }

  std::string getShowed()const{
      if(point==1)return "A";
      else if(point==11)return "J";
      else if(point==12)return "Q";
      else if(point==13)return "K";
      else if(point==14)return "小";
      else if(point==15)return "大";
      else if(point==10)return "10";

      std::string out="";
      out+=(char)(point+'0');
      return out;
  }
};

class Plane {
  friend class Cards;

private:
  Card main_begin; // 飞机的三牌主体开始的数
  Card main_end;
  int num; // 主体长度

  int sub;             // 飞机类型，空三或三带一或三带二
  std::vector<Card> a; // 带的牌的数组

public:
  bool can_compare(const Plane &x) {
    if (num != x.num || sub != x.sub)
      return false;
    return true;
  }

  bool operator<(const Plane &x) {
    // 这个函数是假定了可以比较
    return (main_begin < x.main_begin);
  }
};

class Cards {
  friend std::ostream &operator<<(std::ostream &out, const Cards &x) {
    for (auto i : x.cards) {
      out << i.point << ' ';
    }

    if (x.type == Cards::Type::plane) {
      return (out << "plane");
    } else if (x.type == Cards::Type::singal) {
      return (out << "singal");
    } else if (x.type == Cards::Type::pair) {
      return (out << "pair");
    } else if (x.type == Cards::Type::shun) {
      return (out << "shun");
    } else if (x.type == Cards::Type::shun_pair) {
      return (out << "shun_pair");
    } else if (x.type == Cards::Type::bomb) {
      return (out << "bomb");
    } else if (x.type == Cards::Type::king_bomb) {
      return (out << "king_bomb");
    } else if (x.type == Cards::Type::three) {
      return (out << "three");
    } else if (x.type == Cards::Type::three_one) {
      return (out << "three_one");
    } else if (x.type == Cards::Type::three_two) {
      return (out << "three_two");
    } else if (x.type == Cards::Type::four_two) {
      return (out << "four_two");
    } else if (x.type == Cards::Type::unusable) {
      return (out << "unusable");
    } else
      return out;
  }

private:
  std::vector<Card> cards;

  Card first;
  Card second;
  Card third;

  Plane *for_plane = nullptr;

  enum Type {
    singal,    // 单牌 1
    pair,      // 双牌 2
    king_bomb, // 王炸 2
    three,     // 空三 3
    bomb,      // 炸弹 4
    three_one, // 三带一 4
    three_two, // 三带二 5
    // four_one, // 四带一
    four_two,  // 四带二 6
    shun,      // 顺子 x(>=5)
    shun_pair, // 连对 x(>=6)
    plane,     // 飞机 x(>=6)
    unusable,  // 不符合规则
  };

  Type type;

  void check();

  bool is_pairs();
  bool is_shun();

  bool check_plane();

public:
  Cards(std::vector<Card> &&ca) : cards(ca) {
    std::sort(cards.begin(), cards.end());
    check();
  }
  ~Cards() { delete for_plane; }

  int length() const { return cards.size(); }
  bool valiable() const { return (type != Cards::Type::unusable); }

  const std::vector<Card>& getCards()const{return cards;}

  int compare_smaller(
      const Cards &x) const; // 1表示比x小，0表示比x大，-1表示不可比较
};

